package cn.schoolwow.quickdao.module.parent.kit;

import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.database.dml.DatabaseManipulation;
import cn.schoolwow.quickdao.module.common.operation.kit.CommonDatabaseOption;
import cn.schoolwow.quickdao.module.common.operation.kit.CommonDatabaseOptionImpl;
import cn.schoolwow.quickdao.module.common.query.kit.QueryOperation;
import cn.schoolwow.quickdao.module.common.query.kit.QueryOperationImpl;
import cn.schoolwow.quickdao.module.database.dcl.kit.DatabaseControl;
import cn.schoolwow.quickdao.module.database.dcl.kit.DatabaseControlImpl;
import cn.schoolwow.quickdao.module.database.ddl.kit.DatabaseDefinition;
import cn.schoolwow.quickdao.module.database.ddl.kit.DatabaseDefinitionInvocationHandler;
import cn.schoolwow.quickdao.module.database.dml.common.domain.ManipulationOption;
import cn.schoolwow.quickdao.module.database.dml.kit.DatabaseManipulationInvocationHandler;
import cn.schoolwow.quickdao.module.database.dql.query.kit.DatabaseQuery;
import cn.schoolwow.quickdao.module.database.dql.query.kit.DatabaseQueryImpl;
import cn.schoolwow.quickdao.module.operation.kit.DAOOperation;
import cn.schoolwow.quickdao.module.operation.kit.DAOOperationImpl;
import cn.schoolwow.quickflow.QuickFlow;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * DAO接口调用代理模式对象
 */
public class DAOInvocationHandler implements InvocationHandler {
    private DatabaseControl databaseControl;
    private DatabaseDefinition databaseDefinition;
    private DatabaseQuery databaseQuery;
    private QueryOperation queryOperation;
    private DAOOperation daoOperation;
    private CommonDatabaseOption commonDatabaseOption;
    private QuickFlow quickFlow;
    private QuickDAOConfig quickDAOConfig;

    public DAOInvocationHandler(QuickFlow quickFlow, QuickDAOConfig quickDAOConfig) {
        this.quickFlow = quickFlow;
        this.quickDAOConfig = quickDAOConfig;
        databaseControl = new DatabaseControlImpl(quickFlow);
        databaseDefinition = (DatabaseDefinition) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class<?>[]{DatabaseDefinition.class}, new DatabaseDefinitionInvocationHandler(quickFlow));
        databaseQuery = new DatabaseQueryImpl(quickFlow);
        queryOperation = new QueryOperationImpl(quickFlow);
        daoOperation = new DAOOperationImpl(quickFlow);
        commonDatabaseOption = new CommonDatabaseOptionImpl(quickFlow);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String interfaceName = method.getDeclaringClass().getSimpleName();
        Object result = null;
        switch (interfaceName) {
            case "DatabaseControl": {
                result = method.invoke(databaseControl, args);
            }
            break;
            case "DatabaseDefinitionQuery":
            case "DatabaseDefinitionAction": {
                result = method.invoke(databaseDefinition, args);
            }
            break;
            case "DatabaseManipulationParent":
            case "DatabaseManipulationOption":
            case "DatabaseManipulationExistQuery":
            case "DatabaseManipulationInstance":
            case "DatabaseManipulationJSON":{
                DatabaseManipulation databaseManipulation = (DatabaseManipulation) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                        new Class<?>[]{DatabaseManipulation.class}, new DatabaseManipulationInvocationHandler(quickFlow));
                ManipulationOption manipulationOption = quickFlow.getContextThreadLocalInstanceData(ManipulationOption.class);
                manipulationOption.databaseManipulation = databaseManipulation;
                result = method.invoke(databaseManipulation, args);
            }
            break;
            case "DatabaseQuery": {
                result = method.invoke(databaseQuery, args);
            }
            break;
            case "QueryOperation":{
                result = method.invoke(queryOperation, args);
            }break;
            case "DAOOperation":{
                result = method.invoke(daoOperation, args);
            }break;
            case "CommonDatabaseOption":{
                result = method.invoke(commonDatabaseOption, args);
            }break;
            case "Object":{
                result = method.invoke(quickDAOConfig, args);
            }break;
            default: {
                throw new IllegalAccessError("不支持调用该方法!方法名:"+method.getName()+",接口名:"+interfaceName);
            }
        }
        return result;
    }
}
